use std::{sync::Arc, time::{SystemTime, UNIX_EPOCH}};

use prisma_client_rust::{QueryError, WhereQuery, Direction};
use serde::{Serialize, Deserialize};
use uuid::Uuid;

use crate::prisma::{PrismaClient, record};
use rspc::Type;

#[derive(Clone, Serialize, Deserialize, Type, Debug)]
pub struct SaveRecordData {
    pub uuid: Option<Uuid>,
    pub relation_uuid: String,
    pub content: String,
    pub module: String
}

#[derive(Clone, Serialize, Deserialize, Type, Debug)]
pub struct RecordParams {
    pub relation_uuid: Option<String>,
    pub module: Option<String>,
    pub start: Option<String>,
    pub end: Option<String>
}

#[derive(Clone, Serialize, Deserialize, Type, Debug)]
pub struct RecordLatest {
    pub module: String,
}

pub struct RecordManager {
}

impl RecordManager {
    pub async fn get(client: Arc<PrismaClient>, args: RecordParams) -> Result<Vec<crate::prisma::record::Data>, QueryError> {
        let mut query = client
            .record()
            .find_many(vec![]);

        if !args.relation_uuid.is_none() {
            query.add_where(record::relation_uuid::equals(args.relation_uuid.unwrap().to_string()));
        }

        if !args.module.is_none() {
            query.add_where(record::module::equals(args.module.unwrap().to_string()));
        }

        if !args.start.is_none() {
            query
                .add_where(record::approval_at::gte(args.start.unwrap().to_string()));
        }

        if !args.end.is_none() {
            query
                .add_where(record::approval_at::lte(args.end.unwrap().to_string()));
        }

        Ok(
            query
                .order_by(record::sended_at::order(Direction::Desc))
                .exec()
                .await?
        )
    }

    pub async fn save(client: Arc<PrismaClient>, args: SaveRecordData) -> Result<(), QueryError> {
        println!("{:?}", args);
        let uuid = if args.uuid.is_none() {
            Uuid::new_v4()
        } else {
            args.uuid.unwrap()
        };
        println!("{:?}", uuid);

        let _ = client
            .record()
            .upsert(
                record::uuid::equals(uuid.clone().to_string()),
                // uuid, content, module
                (
                    uuid.clone().to_string(),
                    args.relation_uuid.clone().to_string(),
                    args.content.clone().to_string(),
                    args.module.clone().to_string(),
                    SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs().to_string(),
                    vec![
                        // record::relation_uuid::set(args.relation_uuid.clone().to_string())
                    ]
                ),
                vec![
                        record::relation_uuid::set(args.relation_uuid.clone().to_string()),
                        record::uuid::set(uuid.clone().to_string()),
                        record::content::set(args.content.clone().to_string()),
                        record::module::set(args.module.clone().to_string())
                    ]
            ).exec().await?;

        Ok(())
    }

    pub async fn latest(client: Arc<PrismaClient>, args: RecordLatest) -> Result<Vec<record::Data>, QueryError> {
        let result = client
            .record()
            .find_many(vec![
                record::module::equals(args.module.clone().to_string())
            ])
            .order_by(
                record::created_at::order(Direction::Asc)
            )
            .take(1)
            .exec()
            .await?;

        Ok(result)
    }
}
